package com.starblink.search.result.ui.cell

import android.content.res.ColorStateList
import android.graphics.drawable.RotateDrawable
import android.util.ArrayMap
import android.view.ViewGroup
import android.view.inputmethod.EditorInfo
import androidx.core.content.ContextCompat
import androidx.core.widget.addTextChangedListener
import com.google.android.flexbox.AlignItems
import com.google.android.flexbox.FlexWrap
import com.google.android.flexbox.FlexboxLayoutManager
import com.google.android.material.button.MaterialButton
import com.starblink.android.basic.adapter.BaseBindingVH
import com.starblink.android.basic.adapter.BaseVH
import com.starblink.android.basic.adapter.MutableAdapter
import com.starblink.android.basic.ext.*
import com.starblink.android.basic.extension.dp2px
import com.starblink.basic.ext.rotate0
import com.starblink.basic.ext.rotate180
import com.starblink.basic.ext.screenWidth
import com.starblink.basic.style.R
import com.starblink.basic.style.view.recyclerview.MaxLineFlexboxLayoutManager
import com.starblink.search.databinding.*
import com.starblink.search.result.repository.model.*
import java.lang.Integer.min


private val containerWidth = screenWidth * (327.0 / 375.0) - 32.dp2px()

private const val expandCloseMaxLine = 3

internal class DrawerTitleCell(binding: CellDrawerTitleBinding) :
    BaseBindingVH<DrawerTitleModel, CellDrawerTitleBinding>(binding) {

    override fun onBind(model: DrawerTitleModel, position: Int) {
        /*itemView.layoutParams = ViewGroup.MarginLayoutParams(
            ViewGroup.MarginLayoutParams.MATCH_PARENT,
            ViewGroup.MarginLayoutParams.WRAP_CONTENT
        ).apply {
            topMargin = if (position == 0) 44.dp2px() else 0
        }*/
        binding.text.text = model.text
    }

}

internal class DrawerInputCell(binding: CellDrawerPriceBinding) :
    BaseBindingVH<DrawerPriceInputModel, CellDrawerPriceBinding>(binding) {

    private var minCall: ((number: Double?) -> Unit)? = null
    private var maxCall: ((number: Double?) -> Unit)? = null

    init {
        setIsRecyclable(false)
        binding.inputMax.enableCorner(8.dp2px())
        binding.inputMin.enableCorner(8.dp2px())
        binding.inputMin.addTextChangedListener {
            it?.toString()?.run {
                minCall?.invoke(
                    try {
                        toDouble()
                    } catch (e: Exception) {
                        e.printStackTrace()
                        null
                    }
                )
            }
        }
        binding.inputMax.addTextChangedListener {
            it?.toString()?.run {
                maxCall?.invoke(
                    try {
                        toDouble()
                    } catch (e: Exception) {
                        e.printStackTrace()
                        null
                    }
                )
            }
        }
        binding.inputMin.setOnEditorActionListener { v, actionId, event ->
            if (actionId == EditorInfo.IME_ACTION_DONE) {
                v.clearFocus()
            }
            false
        }
        binding.inputMax.setOnEditorActionListener { v, actionId, event ->
            if (actionId == EditorInfo.IME_ACTION_DONE) {
                v.clearFocus()
            }
            false
        }
    }

    override fun onBind(model: DrawerPriceInputModel, position: Int) {
        binding.inputMin.setText(model.min?.toString())
        binding.inputMax.setText(model.max?.toString())
        minCall = {
            model.min = it
        }
        maxCall = {
            model.max = it
        }
    }

}

internal class DrawerBrandCell(binding: CellDrawerPropertyBinding) :
    BaseBindingVH<SelectableBrandWrap, CellDrawerPropertyBinding>(binding) {

    private val list = arrayListOf<SelectableBrand>()

    private var selectCache = ArrayMap<Int, SelectableBrand>()

    private val view4Cal = CellDrawerPropertyItemBinding.inflate(itemView.inflater,  itemView as ViewGroup, false)

    private val adapter = object : MutableAdapter(list) {
        override fun onBindViewHolder(holder: BaseVH<*>, position: Int) {
            (holder as BrandItemCell?)?.selectCache = selectCache
            super.onBindViewHolder(holder, position)
        }

    }.apply {
        addVhDelegate {
            BrandItemCell(
                CellDrawerPropertyItemBinding.inflate(it.inflater, it, false),
                selectCache
            ) {
                refreshItem(it)
            }
        }
    }

    private var arrowDrawable: RotateDrawable? = null

    private var expanded: Boolean = false

    private var threeLineCount = 0

    private val gapSize = 8.dp2px()

    private val layoutManager = MaxLineFlexboxLayoutManager(itemView.context).apply {
        this.flexWrap = FlexWrap.WRAP
        this.alignItems = AlignItems.FLEX_START
    }

    init {
        setIsRecyclable(false)
        binding.recycler.layoutManager = layoutManager
        binding.recycler.adapter = adapter

        binding.title.setOnClickListener {
            arrowDrawable?:return@setOnClickListener
            if (binding.recycler.isVisible && expanded) {
                arrowDrawable?.rotate0()
                expanded = false
                layoutManager.maxLine = expandCloseMaxLine
                adapter.refreshAll()
            } else {
                expanded = true
                arrowDrawable?.rotate180()
                layoutManager.maxLine = FlexboxLayoutManager.NOT_SET
                adapter.refreshAll()
            }
        }
    }


    override fun onBind(model: SelectableBrandWrap, position: Int) {
        binding.title.text = string(R.string.popular_brands)
        list.clear()
        list.addAll(model.brands)
        selectCache = model.selectCache

        if (!model.hasMoreProperty) {
            binding.recycler.visible()
            arrowDrawable = null
        } else {
            if (arrowDrawable == null && threeLineCount == 0) {
                // 估算出是否超三行
                var width = 0f
                while (threeLineCount < list.size && width < containerWidth * 3) {
                    width += view4Cal.btn.run {
                        min(paint.measureText(list[threeLineCount].source.name).toInt() + paddingLeft + paddingRight, containerWidth.toInt()) + gapSize
                    }
                    threeLineCount++
                }
                val over3Line = width > containerWidth * 3

                if (over3Line) {
                    layoutManager.maxLine = expandCloseMaxLine
                    arrowDrawable = RotateDrawable().apply {
                        drawable = ContextCompat.getDrawable(
                            itemView.context,
                            R.drawable.ic_svg_arrow_down_16_16
                        )
                    }
                    binding.title.setCompoundDrawablesWithIntrinsicBounds(
                        null,
                        null,
                        arrowDrawable,
                        null
                    )
                }

            }
        }


        adapter.refreshAll()
    }

    private fun refreshItem(index: Int) {
        adapter.notifyItemChanged(index)
    }

}

internal class DrawerPropertyCell(binding: CellDrawerPropertyBinding) :
    BaseBindingVH<SelectablePropertyWrap, CellDrawerPropertyBinding>(binding) {

    private val view4Cal = CellDrawerPropertyItemBinding.inflate(itemView.inflater, itemView as ViewGroup, false)

    private val list = arrayListOf<SelectableProperty>()

    private var selectCache = ArrayMap<Int, SelectableProperty>()


    private val adapter = object : MutableAdapter(list) {

        override fun onBindViewHolder(holder: BaseVH<*>, position: Int) {
            (holder as PropertyItemCell?)?.selectCache = selectCache
            super.onBindViewHolder(holder, position)
        }

    }.apply {
        addVhDelegate {
            PropertyItemCell(
                CellDrawerPropertyItemBinding.inflate(it.inflater, it, false),
                selectCache
            ) {
                refreshItem(it)
            }
        }
    }

    private var arrowDrawable: RotateDrawable? = null

    private val gapSize = 8.dp2px()

    private var threeLineCount = 0

    private val layoutManager = MaxLineFlexboxLayoutManager(itemView.context).apply {

    }

    private var expandClose = true

    init {
        setIsRecyclable(false)
        binding.recycler.layoutManager = layoutManager
        binding.recycler.adapter = adapter
        binding.title.setOnClickListener {
            arrowDrawable?:return@setOnClickListener
            it.tag?:return@setOnClickListener
            val model = it.tag as SelectablePropertyWrap
            if (expandClose) {
                model.expand = if (model.expand) {
                    arrowDrawable?.rotate0()
                    binding.recycler.gone()
                    false
                } else {
                    arrowDrawable?.rotate180()
                    binding.recycler.visible()
                    true
                }
            } else {
                model.expand = if (model.expand) {
                    arrowDrawable?.rotate0()
                    layoutManager.maxLine = expandCloseMaxLine
                    adapter.refreshAll()
                    false
                } else {
                    arrowDrawable?.rotate180()
                    layoutManager.maxLine = FlexboxLayoutManager.NOT_SET
                    adapter.refreshAll()
                    true
                }
            }
        }
    }


    override fun onBind(model: SelectablePropertyWrap, position: Int) {
        binding.title.text = model.source.name
        binding.title.tag = model
        list.clear()
        list.addAll(model.properties)

        expandClose = model.drawerDataIndex > 2
        // 前三个属性包括品牌首次需自动展开
        if (expandClose) {
            if (arrowDrawable == null) {
                arrowDrawable = RotateDrawable().apply {
                    drawable = ContextCompat.getDrawable(itemView.context, R.drawable.ic_svg_arrow_down_16_16)
                }
                binding.title.setCompoundDrawablesWithIntrinsicBounds(null, null, arrowDrawable, null)
            }
            if (model.expand.not()) {
                arrowDrawable?.rotate0()
            } else {
                arrowDrawable?.rotate180()
            }
            layoutManager.maxLine = FlexboxLayoutManager.NOT_SET
            binding.recycler.visibleOrGone(model.expand)
        } else {
            if (threeLineCount == 0) {
                // 估算出是否超三行
                var width = 0f
                while (threeLineCount < list.size && width < containerWidth * 3) {
                    width += view4Cal.btn.run {
                        min(paint.measureText(list[threeLineCount].text).toInt() + paddingLeft + paddingRight, containerWidth.toInt()) + gapSize
                    }
                    threeLineCount++
                }
                val over3Line = width > containerWidth * 3

                // 超过三行
                if (over3Line) {
                    model.expand = false
                    layoutManager.maxLine = expandCloseMaxLine
                    arrowDrawable = RotateDrawable().apply {
                        drawable = ContextCompat.getDrawable(
                            itemView.context,
                            R.drawable.ic_svg_arrow_down_16_16
                        )
                    }
                } else {
                    model.expand = true
                    arrowDrawable = null
                }
                binding.recycler.visible()
            } else {
                arrowDrawable = null
                binding.recycler.visibleOrGone(model.expand)
            }
        }
        binding.title.setCompoundDrawablesWithIntrinsicBounds(
            null,
            null,
            arrowDrawable,
            null
        )


        selectCache = model.selectCache
        adapter.refreshAll()
    }

    private fun refreshItem(index: Int) {
        adapter.notifyItemChanged(index)
    }
}

private class PropertyItemCell(
    binding: CellDrawerPropertyItemBinding,
    var selectCache: ArrayMap<Int, SelectableProperty>,
    private val click: ((position: Int) -> Unit)? = null
) : BaseBindingVH<SelectableProperty, CellDrawerPropertyItemBinding>(binding) {


    override fun onBind(model: SelectableProperty, position: Int) {
        binding.btn.setOnClickListener {
            if (selectCache[position] == model) {
                selectCache.remove(position)
            } else {
                selectCache[position] = model
            }
            //onBind(model, position)
            click?.invoke(position)
        }
        binding.btn.text = model.text

        setBtn(selectCache[position] == model, binding.btn)
    }

}

private class BrandItemCell(
    binding: CellDrawerPropertyItemBinding,
    var selectCache: ArrayMap<Int, SelectableBrand>,
    private val click: ((position: Int) -> Unit)? = null
) : BaseBindingVH<SelectableBrand, CellDrawerPropertyItemBinding>(binding) {

    override fun onBind(model: SelectableBrand, position: Int) {
        binding.btn.setOnClickListener {
            if (selectCache[position] == model) {
                selectCache.remove(position)
            } else {
                selectCache[position] = model
            }
            //onBind(model, position)
            click?.invoke(position)
        }
        binding.btn.text = model.source.name
        setBtn(selectCache[position] == model, binding.btn)
    }

}

private fun setBtn(select: Boolean, btn: MaterialButton) {
    if (select) {
        btn.setTextColor(btn.color(R.color.sk_red600))
        btn.strokeWidth = 1.dp2px()
        btn.setStrokeColorResource(R.color.sk_red600)
        btn.backgroundTintList = ColorStateList.valueOf(btn.color(R.color.sk_red50))
    } else {
        btn.setTextColor(btn.color(R.color.sk_gray600))
        btn.strokeWidth = 0
        btn.backgroundTintList = ColorStateList.valueOf(btn.color(R.color.sk_gray50))
    }
}